/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.multioperacion.data;

import com.multioperacion.exception.MultiopPersistException;
import com.multioperacion.exception.MultiopFindException;
import com.multioperacion.exception.MultiopMergeException;
import com.multioperacion.exception.MultiopRemoveException;
import java.util.List;
import javax.persistence.EntityManager;


/**
 *
 * @author gabrielbran
 */
public abstract class AbstractManager {

    /**
     * Define el paquete donde se encuentrasn las entidades.
     */
    private final String paqueteModelo = "com.multioperacion.model.";
    Conexion conexion;

    /**
     * Devuelve la instancia de EntityManager activa.
     * @return EntityManager
     */
    public EntityManager getEm() {
        return conexion.getEm();
    }

    public AbstractManager() {
        conexion = new Conexion();
    }

    /**
     * Persistir Objeto.
     * @param o Objeto a persistir a la base de datos.
     * @return Objeto enviado a la base de datos.
     */
    public Object persistObject(Object o) throws MultiopPersistException {
        try {
            getEm().getTransaction().begin();
            getEm().persist(o);
            getEm().getTransaction().commit();
        } catch (Exception e) {
            throw new MultiopPersistException("Error al almacenar objeto : " + o.getClass().toString(), e);
        }
        return null;
    }

    /**
     * Actualizar Objeto.
     * @param o Objeto a actualizar.
     * @return  Objeto Actualizado.
     */
    public Object mergeObject(Object o) throws MultiopMergeException {
        try {
            getEm().getTransaction().begin();
            getEm().merge(o);
            getEm().getTransaction().commit();
        } catch (Exception e) {
            throw new MultiopMergeException("Error al modificar objeto : " + o.getClass().toString(), e);
        }
        return null;
    }

    /**
     * Eliminar Objeto.
     * @param o Objeto a Eliminar.
     */
    public void removeObject(Object o) throws MultiopRemoveException {
        try {
            getEm().getTransaction().begin();
            getEm().remove(getEm().merge(o));
            getEm().getTransaction().commit();
        } catch (Exception e) {
            throw new MultiopRemoveException("Error al eliminar objeto : " + o.getClass().toString(), e);
        }
    }

    /**
     * Buscar Objeto por llave primaria.
     * @param pk Objeto que representa la llave primaria.
     * @return Objeto encontrado.
     */
    public Object findById(Object pk) throws Exception, MultiopFindException {
        try {
            return getEm().find(Class.forName(paqueteModelo + getEntityName()), pk);
        } catch (ClassNotFoundException cfe) {
            throw new Exception("Error Clase no encontrada " + getEntityName(), cfe);
        } catch (Exception e) {
            throw new MultiopFindException("Error al obtener registro de " + getEntityName() + " con ID : " + pk.toString(), e);
        }
    }

    /**
     * Listar todos loe elementos de la misma familia.
     * @return Lista de Objetos.
     */
    public List getEntityList() throws MultiopFindException {
        try {
            return getEm().createQuery("select o from " + getEntityName() + " o").getResultList();
        } catch (Exception e) {
            throw new MultiopFindException("Error al obtener registros de " + getEntityName(), e);
        }

    }

    /**
     * Tipo de entidad que se esta procesando.
     * @return String.
     */
    public abstract String getEntityName();
}
